package com.easylinkin.linkappapi.openapi.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.easylinkin.linkappapi.common.model.RequestModel;
import com.easylinkin.linkappapi.common.service.CommonService;
import com.easylinkin.linkappapi.common.utils.DateUtil;
import com.easylinkin.linkappapi.device.entity.Device;
import com.easylinkin.linkappapi.device.service.DeviceService;
import com.easylinkin.linkappapi.deviceattributestatus.entity.DeviceAttributeStatus;
import com.easylinkin.linkappapi.deviceattributestatus.service.DeviceAttributeStatusService;
import com.easylinkin.linkappapi.lobar.dto.LaborCompanyGroupDto;
import com.easylinkin.linkappapi.lobar.dto.LaborCompanyProjectDTO;
import com.easylinkin.linkappapi.lobar.dto.UserGateDTO;
import com.easylinkin.linkappapi.lobar.dto.UserProjectDTO;
import com.easylinkin.linkappapi.lobar.entity.*;
import com.easylinkin.linkappapi.lobar.mapper.*;
import com.easylinkin.linkappapi.lobar.service.GateService;
import com.easylinkin.linkappapi.lobar.service.GroupService;
import com.easylinkin.linkappapi.lobar.service.LaborCompanyProjectService;
import com.easylinkin.linkappapi.lobar.service.LaborCompanyService;
import com.easylinkin.linkappapi.lobar.vo.LaborCompanyGroupVo;
import com.easylinkin.linkappapi.lobar.vo.UserProjectVo;
import com.easylinkin.linkappapi.openapi.dto.DatapushDTO;
import com.easylinkin.linkappapi.openapi.dto.SystemDockDevice;
import com.easylinkin.linkappapi.openapi.dto.SystemDockInfo;
import com.easylinkin.linkappapi.openapi.dto.SystemDocking;
import com.easylinkin.linkappapi.openapi.dto.systemDock.*;
import com.easylinkin.linkappapi.openapi.mapper.SystemDockDeviceMapper;
import com.easylinkin.linkappapi.openapi.mapper.SystemDockInfoMapper;
import com.easylinkin.linkappapi.openapi.mapper.SystemDockingMapper;
import com.easylinkin.linkappapi.openapi.service.SystemDockDeviceService;
import com.easylinkin.linkappapi.openapi.service.SystemDockingService;
import com.easylinkin.linkappapi.openapi.util.AESUtil;
import com.easylinkin.linkappapi.openapi.util.DeviceInfoPostUtil;
import com.easylinkin.linkappapi.openapi.util.HttpClientUtil;
import com.easylinkin.linkappapi.safe.util.ImageUtil;
import com.easylinkin.linkappapi.security.context.LinkappUserContextProducer;
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.time.ZoneId;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.easylinkin.linkappapi.security.entity.LinkappUser;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.methods.HttpGet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;

/**
 * SystemDocking表服务实现类
 *
 * @author CodeGenerator
 * @date 2023/05/12
 */
@Slf4j
@Service("systemDockingService")
@Component
public class SystemDockingServiceImpl extends ServiceImpl<SystemDockingMapper, SystemDocking>
        implements SystemDockingService {

    @Resource
    private CommonService commonService;

    @Resource
    private LinkappUserContextProducer linkappUserContextProducer;

    @Resource
    private SystemDockDeviceService systemDockDeviceService;

    @Resource
    private SystemDockDeviceMapper systemDockDeviceMapper;

    @Autowired
    private DeviceService deviceService;

    @Resource
    private DeviceAttributeStatusService attributeStatusService;

    @Resource
    private SystemDockInfoMapper infoMapper;


    @Resource
    private SystemDockingMapper systemDockingMapper;

    @Autowired
    private LaborCompanyProjectService laborCompanyProjectService;

    @Resource
    private LaborCompanyMapper companyMapper;

    @Autowired
    private GroupService groupService;

    @Resource
    private UserProjectMapper userProjectMapper;

    @Resource
    private UserClockMapper userClockMapper;

    @Value("${systemPush.url:http://183.95.190.176:9050/}")
    private String systemPushUrl;

    @Value("${systemdocking.projuid}")
    private String projUid;

    @Value("${systemdocking.urlprefix}")
    private String urlPrefix;

    @Resource
    private GateMapper gateMapper;

    @Override
    @Transactional
    public boolean saveOne(SystemDocking one) {
        // 不保存末尾的/
        if(one.getUrl().endsWith("/")) {
            one.setUrl(one.getUrl().substring(0, one.getUrl().length() - 1));
        }
        boolean save = false;

        if (null == one.getId() || one.getId() == 0) {

            QueryWrapper<SystemDocking> qw = new QueryWrapper<>();

            qw.eq("sys_name", one.getSysName());
            qw.eq("tenant_id", linkappUserContextProducer.getNotNullCurrent().getTenantId());

            // 一个系统只能存在一条记录
            List<SystemDocking> selectList = baseMapper.selectList(qw);

            if (selectList != null && selectList.size() > 0) {

                save = false;
                throw new RuntimeException("同一个系统只能存在一条记录");
            }

            one.setCreateor(linkappUserContextProducer.getNotNullCurrent().getId().toString());
            one.setCreateTime(new Date());
            one.setModifyTime(new Date());
            one.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
            save = save(one);

            if (save) {
                // 储存关联数据
                one.getSystemDockDeviceList().forEach(item -> {
                    item.setLinkId(one.getId());
                });

                systemDockDeviceService.saveAll(one.getSystemDockDeviceList());
            }

        } else {

            one.setModifier(linkappUserContextProducer.getNotNullCurrent().getId().toString());
            one.setModifyTime(new Date());
            save = retBool(baseMapper.updateById(one));

            if (save) {
                // 先删除原先绑定的数据
                systemDockDeviceService.deletedBylinkId(one.getId());

                // 储存关联数据
                one.getSystemDockDeviceList().forEach(item -> {
                    item.setLinkId(one.getId());
                });

                systemDockDeviceService.saveAll(one.getSystemDockDeviceList());
            }
        }

        if (one.getSysName().equals("湖北省建设厅智慧工地管理平台") ) {
            // 设备信息注册
            deviceRegister(one);
        } else if(one.getSysName().equals("武汉市房屋市政工程智慧工地管理平台")) {
            // 设备信息注册
            fangWuShiZhengDeviceRegister(one);
        } else if (one.getSysName().equals("武汉市东湖高新区智慧工地管理平台")) {
            dongHuGaoXinDeviceRegister(one);
        } else if (one.getSysName().equals("光谷文化中心智慧建造云平台")) {
            zhiHuiJianZaoDeviceRegister(one);
        }
        return save;
    }



    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateOne(SystemDocking systemDocking) {
        Assert.notNull(systemDocking.getId(), "id不能为空");
        commonService.setModifyInfo(systemDocking);
        // systemDocking.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
        return updateById(systemDocking);
    }

    @Override
    public IPage<SystemDocking> selectPage(Page page, SystemDocking systemDocking) {

        systemDocking.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());

        IPage<SystemDocking> iPage = baseMapper.selectPage(page, systemDocking);

        List<SystemDocking> records = iPage.getRecords();

        records.forEach(item -> {

            SystemDockDevice search = new SystemDockDevice();

            search.setLinkId(item.getId());

            item.setSystemDockDeviceList(systemDockDeviceMapper.selectPage(search));
        });

        iPage.setRecords(records);

        return iPage;
    }

    @Override
    public List<SystemDocking> selectList(SystemDocking systemDocking) {

        if (StringUtils.isBlank(systemDocking.getTenantId())) {

            systemDocking.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
        }

        List<SystemDocking> records = baseMapper.selectPage(systemDocking);

        records.forEach(item -> {

            SystemDockDevice search = new SystemDockDevice();
            search.setLinkId(item.getId());
            search.setDeviceCode(systemDocking.getDeivceCode());
            search.setIsSync(systemDocking.getIsSync());

            item.setSystemDockDeviceList(systemDockDeviceMapper.selectPage(search));
        });

        return records;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteByIds(List<Long> idList) {

        //删除关联的设备
        systemDockDeviceService.deletedBylinkIds(idList);
        return removeByIds(idList);

    }

    @Override
    public void export(SystemDocking systemDocking, HttpServletRequest request, HttpServletResponse response) {

    }

    @Override
    public SystemDocking getOneById(Serializable id) {
        return baseMapper.getOneById(id);
    }

    /**
     * 房屋市政注册
     * @param
     */
    private void fangWuShiZhengDeviceRegister(SystemDocking sysDocking) {

        List<SystemDockDevice> devices = sysDocking.getSystemDockDeviceList();

        if (devices != null && devices.size() > 0) {

            Device device = new Device();

            devices.stream().filter(dock -> dock.getIsSync() == 1).forEach(item -> {


                String url = "";
                String data = "";
                // 根据设备id获取设备属性信息
                device.setId(item.getDeviceId());
                List<Device> list = deviceService.selectDevices(device);

                if (list != null && list.size() > 0) {

                    Device d = list.get(0);

                    List<DeviceAttributeStatus> deviceAttributeStatus = getDeviceAttributeStatus(d);
                    // 转为map 方便操作
                    Map<String, Object> map = new HashMap<>();

                    if (deviceAttributeStatus != null && deviceAttributeStatus.size() > 0) {
                        // 转为map 方便操作   //排除空值
                        map = deviceAttributeStatus.stream().filter(entry -> StringUtils.isNotBlank(entry.getPropCode()) && StringUtils.isNotBlank(entry.getPropValue()))
                                .collect(Collectors.toMap(DeviceAttributeStatus::getPropCode, DeviceAttributeStatus::getPropValue));
                    }

                    RaiseDustDTO one = new RaiseDustDTO();

                    one.setDeviceName(d.getName());// 设备名称
                    one.setDeviceNo(d.getCode());// 设备编号
                    one.setDeviceModel(d.getDeviceUnitCode());// 设备型号
                    one.setDeviceCategory(d.getDeviceTypeName());// 设备类型
                    one.setPositionType("007");// 目前设备信息与部位信息未能完全匹配，先设置为其他部位007
                    one.setMonitorPlace(StringUtils.isBlank(d.getSite()) ? "暂无" : d.getSite());// 安装位置
                    one.setFilingNo(d.getFilingNo());// 备案编号
                    if (item.getType() == 0) {
                        // 扬尘设备
                        data = JSONObject.toJSONString(one);
                        url = "/api/device/register/environment";

                    } else if (item.getType() == 1) {
                        // 塔机设备注册
                        data = towerCraneInfo(one, map);
                        url = "/api/device/register/towerCrane";

                    } else if (item.getType() == 2) {
                        // 升降机设备
                        data = elevatorInfo(one, map);
                        url = "/api/device/register/elevator";

                    } else if (item.getType() == 3) {

                        String videoUrl = String.format(
                                "https://open.ys7.com/ezopen/h5/iframe?bSupporDoubleClickFull=0&url=%s&autoplay=1&audio=1&accessToken=%s&templete=1&id=video0&decoderVersion=",
                                Objects.toString(map.get("ezopen"), ""), Objects.toString(map.get("accessToken"), ""));

                        one.setVideoStreamUrl(videoUrl);

                        data = JSONObject.toJSONString(one);
                        url = "/api/device/register/video";
                    }
                }

                if (StringUtils.isNotBlank(url)) {
                    String tempSystemPushUrl;
                    if(StringUtils.isNotEmpty(sysDocking.getUrl())){
                        tempSystemPushUrl = sysDocking.getUrl();
                    } else {
                        tempSystemPushUrl = systemPushUrl;
                    }

                    // 临时：先调设备心跳接口模拟在线
                    SystemDockServerDTO systemDockServerDTO = new SystemDockServerDTO();
                    if (list != null) {
                        systemDockServerDTO.setDeviceNo(list.get(0).getCode());
                    }
                    switch (item.getType())
                    {
                        case 0:
                            systemDockServerDTO.setDeviceType(1);
                            break;
                        case 1:
                            systemDockServerDTO.setDeviceType(2);
                            break;
                        case 2:
                            systemDockServerDTO.setDeviceType(3);
                            break;
                        default:
                            break;
                    }
                    if( systemDockServerDTO.getDeviceType()!=null) {
                        String serverUrl = "/api/device/getServer";
                        String serverData = JSONObject.toJSONString(systemDockServerDTO);
                        DeviceInfoPostUtil.handleData(sysDocking.getAppid(), sysDocking.getSecret(), serverData,
                                tempSystemPushUrl + serverUrl);
                    }


                    String respData = DeviceInfoPostUtil.handleData(sysDocking.getAppid(), sysDocking.getSecret(), data,
                            tempSystemPushUrl + url);

                    //saveInfo(systemPushUrl + url, respData, data);
                }

            });

        }
    }

    /**
     * 东湖高新区注册
     * @param
     */
    private void dongHuGaoXinDeviceRegister(SystemDocking sysDocking) {

        List<SystemDockDevice> devices = sysDocking.getSystemDockDeviceList();

        if (devices != null && devices.size() > 0) {

            Device device = new Device();

            devices.stream().filter(dock -> dock.getIsSync() == 1).forEach(item -> {


                String url = "";
                String data = "";
                // 根据设备id获取设备属性信息
                device.setId(item.getDeviceId());
                List<Device> list = deviceService.selectDevices(device);

                if (list != null && list.size() > 0) {

                    Device d = list.get(0);

                    List<DeviceAttributeStatus> deviceAttributeStatus = getDeviceAttributeStatus(d);
                    // 转为map 方便操作
                    Map<String, Object> map = new HashMap<>();

                    if (deviceAttributeStatus != null && deviceAttributeStatus.size() > 0) {
                        // 转为map 方便操作   //排除空值
                        map = deviceAttributeStatus.stream().filter(entry -> StringUtils.isNotBlank(entry.getPropCode()) && StringUtils.isNotBlank(entry.getPropValue()))
                                .collect(Collectors.toMap(DeviceAttributeStatus::getPropCode, DeviceAttributeStatus::getPropValue));
                    }

                    RaiseDustDTO one = new RaiseDustDTO();

                    one.setDeviceName(d.getName());// 设备名称
                    one.setDeviceNo(d.getCode());// 设备编号
                    one.setDeviceModel(d.getDeviceUnitCode());// 设备型号
                    one.setDeviceCategory(d.getDeviceTypeName());// 设备类型
                    one.setPositionType("007");// 目前设备信息与部位信息未能完全匹配，先设置为其他部位007
                    one.setMonitorPlace(StringUtils.isBlank(d.getSite()) ? "暂无" : d.getSite());// 安装位置

                    if (item.getType() == 0) {
                        // 扬尘设备
                        data = JSONObject.toJSONString(one);
                        url = "/api/device/register/environment";

                    } else if (item.getType() == 1) {
                        // 塔机设备注册
                        data = towerCraneInfo(one, map);
                        url = "/api/device/register/towerCrane";

                    } else if (item.getType() == 2) {
                        // 升降机设备
                        data = elevatorInfo(one, map);
                        url = "/api/device/register/elevator";

                    } else if (item.getType() == 3) {

                        String videoUrl = String.format(
                                "https://open.ys7.com/ezopen/h5/iframe?bSupporDoubleClickFull=0&url=%s&autoplay=1&audio=1&accessToken=%s&templete=1&id=video0&decoderVersion=",
                                Objects.toString(map.get("ezopen"), ""), Objects.toString(map.get("accessToken"), ""));

                        one.setVideoStreamUrl(videoUrl);

                        data = JSONObject.toJSONString(one);
                        url = "/api/device/register/video";
                    }
                }

                if (StringUtils.isNotBlank(url)) {
                    String tempSystemPushUrl;
                    if(StringUtils.isNotEmpty(sysDocking.getUrl())){
                        tempSystemPushUrl = sysDocking.getUrl();
                    } else {
                        tempSystemPushUrl = systemPushUrl;
                    }

                    // 临时：先调设备心跳接口模拟在线
                    SystemDockServerDTO systemDockServerDTO = new SystemDockServerDTO();
                    if (list != null) {
                        systemDockServerDTO.setDeviceNo(list.get(0).getCode());
                    }
                    switch (item.getType())
                    {
                        case 0:
                            systemDockServerDTO.setDeviceType(1);
                            break;
                        case 1:
                            systemDockServerDTO.setDeviceType(2);
                            break;
                        case 2:
                            systemDockServerDTO.setDeviceType(3);
                            break;
                        default:
                            break;
                    }
//                    if( systemDockServerDTO.getDeviceType()!=null) {
//                        String serverUrl = "/api/device/getServer";
//                        String serverData = JSONObject.toJSONString(systemDockServerDTO);
//                        DeviceInfoPostUtil.handleData(sysDocking.getAppid(), sysDocking.getSecret(), serverData,
//                                tempSystemPushUrl + serverUrl);
//                    }


                    String respData = DeviceInfoPostUtil.handleData(sysDocking.getAppid(), sysDocking.getSecret(), data,
                            tempSystemPushUrl + url);

                    //saveInfo(systemPushUrl + url, respData, data);
                }

            });

        }
    }

    /**
     * 智慧建造云注册
     * @param
     */
    private void zhiHuiJianZaoDeviceRegister(SystemDocking sysDocking) {

        List<SystemDockDevice> devices = sysDocking.getSystemDockDeviceList();

        if (devices != null && devices.size() > 0) {

            Device device = new Device();

            devices.stream().filter(dock -> dock.getIsSync() == 1).forEach(item -> {
                if (!Integer.valueOf(3).equals(item.getType())) {
                    String url = "";
                    String data = "";
                    // 根据设备id获取设备属性信息
                    device.setId(item.getDeviceId());
                    List<Device> list = deviceService.selectDevices(device);

                    if (list != null && list.size() > 0) {

                        Device d = list.get(0);

                        List<DeviceAttributeStatus> deviceAttributeStatus = getDeviceAttributeStatus(d);
                        // 转为map 方便操作
                        Map<String, Object> map = new HashMap<>();

                        if (deviceAttributeStatus != null && deviceAttributeStatus.size() > 0) {
                            // 转为map 方便操作   //排除空值
                            map = deviceAttributeStatus.stream().filter(entry -> StringUtils.isNotBlank(entry.getPropCode()) && StringUtils.isNotBlank(entry.getPropValue()))
                                    .collect(Collectors.toMap(DeviceAttributeStatus::getPropCode, DeviceAttributeStatus::getPropValue));
                        }

                        DeviceRegisDTO one = new DeviceRegisDTO();

                        one.setTitle(d.getName());// 设备名称
                        one.setDeviceCode(d.getCode());// 设备编号
                        one.setModelSpec(d.getDeviceUnitCode());// 设备型号
                        // 设备类型
                        switch (item.getType()) {
                            case 0:
                                one.setType("1");
                                break;
                            case 1:
                                one.setType("4");
                                break;
                            case 2:
                                one.setType("5");
                                break;
                            case 4:
                                one.setType("7");
                                break;
                            case 5:
                                one.setType("3");
                                break;
                            case 6:
                                one.setType("6");
                                break;
                            default:
                                break;
                        }
                        one.setAddress(StringUtils.isBlank(d.getSite()) ? "暂无" : d.getSite());// 安装位置
                        one.setProjUid(projUid);
                        one.setEnable("1");

                        data = JSONObject.toJSONString(one);
                        url = "/api_v1/modules/check_devices";
                    }

                    if (StringUtils.isNotBlank(url)) {
                        String tempSystemPushUrl;
                        if(StringUtils.isNotEmpty(sysDocking.getUrl())){
                            tempSystemPushUrl = sysDocking.getUrl();
                        } else {
                            tempSystemPushUrl = systemPushUrl;
                        }

                        String respData = DeviceInfoPostUtil.handleData2(data, tempSystemPushUrl + url);
                    }
                }
                });

        }
    }

    private void deviceRegister(SystemDocking sysDocking) {

        List<SystemDockDevice> devices = sysDocking.getSystemDockDeviceList();

        if (devices != null && devices.size() > 0) {

            Device device = new Device();

            devices.stream().filter(dock -> dock.getIsSync() == 1).forEach(item -> {

                String url = "";
                String data = "";
                // 根据设备id获取设备属性信息
                device.setId(item.getDeviceId());
                List<Device> list = deviceService.selectDevices(device);

                if (list != null && list.size() > 0) {

                    Device d = list.get(0);

                    List<DeviceAttributeStatus> deviceAttributeStatus = getDeviceAttributeStatus(d);
                    // 转为map 方便操作
                    Map<String, Object> map = new HashMap<>();

                    if (deviceAttributeStatus != null && deviceAttributeStatus.size() > 0) {
                        // 转为map 方便操作   //排除空值
                        map = deviceAttributeStatus.stream().filter(entry -> StringUtils.isNotBlank(entry.getPropCode()) && StringUtils.isNotBlank(entry.getPropValue()))
                                .collect(Collectors.toMap(DeviceAttributeStatus::getPropCode, DeviceAttributeStatus::getPropValue));
                    }

                    RaiseDustDTO one = new RaiseDustDTO();

                    one.setDeviceName(d.getName());// 设备名称
                    one.setDeviceNo(d.getCode());// 设备编号
                    one.setDeviceModel(d.getDeviceUnitCode());// 设备型号
                    one.setDeviceCategory(d.getDeviceTypeName());// 设备类型
                    one.setPositionType("007");// 目前设备信息与部位信息未能完全匹配，先设置为其他部位007
                    one.setMonitorPlace(StringUtils.isBlank(d.getSite()) ? "暂无" : d.getSite());// 安装位置

                    if (item.getType() == 0) {
                        // 扬尘设备
                        data = JSONObject.toJSONString(one);
                        url = "/api/device/register/environment";

                    } else if (item.getType() == 1) {
                        // 塔机设备注册
                        data = towerCraneInfo(one, map);
                        url = "/api/device/register/towerCrane";

                    } else if (item.getType() == 2) {
                        // 升降机设备
                        data = elevatorInfo(one, map);
                        url = "/api/device/register/elevator";

                    } else if (item.getType() == 3) {

                        String videoUrl = String.format(
                                "https://open.ys7.com/ezopen/h5/iframe?bSupporDoubleClickFull=0&url=%s&autoplay=1&audio=1&accessToken=%s&templete=1&id=video0&decoderVersion=",
                                Objects.toString(map.get("ezopen"), ""), Objects.toString(map.get("accessToken"), ""));

                        one.setVideoStreamUrl(videoUrl);

                        data = JSONObject.toJSONString(one);
                        url = "/api/device/register/video";
                    }
                }

                if (StringUtils.isNotBlank(url)) {
                    String tempSystemPushUrl;
                    if(StringUtils.isNotEmpty(sysDocking.getUrl())){
                        tempSystemPushUrl = sysDocking.getUrl();
                    } else {
                        tempSystemPushUrl = systemPushUrl;
                    }
                    String respData = DeviceInfoPostUtil.handleData(sysDocking.getAppid(), sysDocking.getSecret(), data,
                            tempSystemPushUrl + url);

                    //saveInfo(systemPushUrl + url, respData, data);
                }

            });

        }
    }

    /**
     * 组装塔机设备注册实体数据
     *
     * @param map
     * @param dto
     * @return
     */
    private String towerCraneInfo(RaiseDustDTO dto, Map<String, Object> map) {

        TowerCraneDTO tc = new TowerCraneDTO();

        tc.setRaiseDustDTO(dto);
        // 起重量
        tc.setAlarmLiftingCapacity(getDouble(Objects.toString(map.get("crane_max_weight"), "0"),
                Objects.toString(map.get("weight_alarm_value"), "0"), true));
        tc.setWarnLiftingCapacity(getDouble(Objects.toString(map.get("crane_max_weight"), "0"),
                Objects.toString(map.get("weight_warn_value"), "0"), true));

        // 力矩
        tc.setAlarmMomentForce(getDouble(Objects.toString(map.get("crane_max_torque"), "0"),
                Objects.toString(map.get("torque_alarm_value"), "0"), true));

        tc.setWarnMomentForce(getDouble(Objects.toString(map.get("crane_max_torque"), "0"),
                Objects.toString(map.get("torque_warn_value"), "0"), true));
        // 幅度限位终点值/起点值
        Double amplitude = getDouble(Objects.toString(map.get("end_range_limit"), "0"),
                Objects.toString(map.get("start_range_limit"), "0"), false);
        tc.setAlarmNearAmplitude(amplitude);
        tc.setAlarmFarAmplitude(amplitude);
        tc.setWarnNearAmplitude(amplitude);
        tc.setWarnFarAmplitude(amplitude);

        // 高度限位
        Double height = getDouble(Objects.toString(map.get("end_height_limit"), "0"),
                Objects.toString(map.get("start_height_limit"), "0"), false);
        tc.setAlarmUpHeight(height);
        tc.setAlarmDownHeight(height);
        tc.setWarnUpHeight(height);
        tc.setWarnDownHeight(height);

        // 倾斜预警/报警

        double ang = getDoubleNotNull(Objects.toString(map.get("tilt_alarm_value"), "0"));
        tc.setAlarmAngleX(ang);
        tc.setAlarmAngleY(ang);
        tc.setWarnAngleX(ang);
        tc.setWarnAngleY(ang);

        // 风速预警
        tc.setAlarmWindSpeed(getDoubleNotNull(Objects.toString(map.get("wind_speed_alarm_value"), "0")));
        tc.setWarnWindSpeed(getDoubleNotNull(Objects.toString(map.get("wind_speed_warn_value"), "0")));

        // 最小回转 起点/终点
        Double rotation = getDouble(Objects.toString(map.get("start_rotation_limit"), "0"),
                Objects.toString(map.get("end_rotation_limit"), "0"), false);
        tc.setAlarmMinDegreeRotation(rotation);
        tc.setAlarmMaxDegreeRotation(rotation);
        tc.setWarnMinDegreeRotation(rotation);
        tc.setWarnMaxDegreeRotation(rotation);

        return JSONObject.toJSONString(tc);
    }

    /**
     * 升降机注册参数
     *
     * @param dto
     * @param map
     * @return
     */
    private String elevatorInfo(RaiseDustDTO dto, Map<String, Object> map) {

        ElevatorDTO one = new ElevatorDTO();

        // 设备基础信息
        one.setRaiseDustDTO(dto);

        one.setWarnCurrentLoad(getDoubleNotNull(Objects.toString(map.get("weight_warn_value"), "0")));
        // 高度预警值，目前没找到高度预警值属性，用高度报警值代替
        one.setWarnHeight(getDoubleNotNull(Objects.toString(map.get("height_alarm_value"), "0")));
        one.setAlarmHeight(getDoubleNotNull(Objects.toString(map.get("height_alarm_value"), "0")));

        one.setWarnAngleX(getDoubleNotNull(Objects.toString(map.get("tilt_warn_value"), "0")));
        one.setWarnAngleY(getDoubleNotNull(Objects.toString(map.get("tilt_warn_value"), "0")));

        one.setAlarmAngleX(getDoubleNotNull(Objects.toString(map.get("tilt_alarm_value"), "0")));
        one.setAlarmAngleY(getDoubleNotNull(Objects.toString(map.get("tilt_alarm_value"), "0")));

        one.setWarnSpeed(getDoubleNotNull(Objects.toString(map.get("speed_warn_value"), "0")));
        one.setAlarmSpeed(getDoubleNotNull(Objects.toString(map.get("speed_alarm_value"), "0")));

        one.setAlarmCurrentLoad(getDoubleNotNull(Objects.toString(map.get("weight_alarm_value"), "0")));

        // one.setAlarmPersonCount(0);

        return JSONObject.toJSONString(one);
    }

    /**
     * 计算百分比并保留两位小数 flag:true 乘法计算，false 除法
     */

    private static Double getDouble(String a, String b, boolean flag) {

        BigDecimal value_1 = new BigDecimal(a);
        BigDecimal value_2 = new BigDecimal(b);

        Double value = 0d;

        if (flag) {

            value = value_1.multiply(value_2).setScale(2, RoundingMode.HALF_UP).doubleValue();
        }

        if (value_2.compareTo(BigDecimal.ZERO) != 0) {

            value = value_1.divide(value_2, 2, BigDecimal.ROUND_HALF_UP).doubleValue();
        }

        return value;
    }

    /**
     * 获取设备状态信息
     */

    private List<DeviceAttributeStatus> getDeviceAttributeStatus(Device device) {

        DeviceAttributeStatus request = new DeviceAttributeStatus();

        request.setDeviceCode(device.getCode());
        request.setVersion(device.getDeviceUnitVersion());
        request.setIsShow(true);

        // 获取塔机设备基础属性信息
        return attributeStatusService.getDeviceRealtimeData(request);
    }

    /**
     * 设备流水上传至对接的系统
     *
     * @param datapushDTO
     */
    @Override
    public void pushToSystemDockHandler(DatapushDTO datapushDTO) {

//        if (datapushDTO == null || datapushDTO.getData() == null) {
//            return;
//        }
        if (datapushDTO.getDevice_unit().equals("SMZMBJ-MQTT-001")) {
            wenHuaZhongXinClockHandaler(datapushDTO);
        } else {
            JSONObject data = datapushDTO.getData();
            // 将查询逻辑放入主线程
            Device device = datapushDTO.getDevice_data_latest();

            SystemDocking docking = new SystemDocking();
            docking.setDeivceCode(datapushDTO.getDevice_id());
            docking.setIsSync(1);// 只对开启了同步的设备进行上传
            docking.setTenantId(device.getTenantId());// push 接口是不需要登录的，手动设置tenantId

            List<SystemDocking> list = selectList(docking);

            if (list == null || list.size() == 0) {
                log.info("pushToSystemDockHandler未获取到需实时上传数据的设备绑定");
                return;
            }
            // 正常来说应该只有一条数据，同系统同一设备只做一次上报
//        docking = list.get(0);
            for(SystemDocking item : list) {
                switch (item.getSysName()) {
                    case "湖北省建设厅智慧工地管理平台" :
                        jianSheTingHandler(item, data ,device);
                        break;
                    case "武汉市房屋市政工程智慧工地管理平台" :
                        fangWuShiZhengHandler(item, data ,device);
                        break;
                    case "武汉市东湖高新区智慧工地管理平台" :
                        dongHuGaoXinHandler(item, data ,device);
                        break;
                    case "光谷文化中心智慧建造云平台" :
                        zhiHuiJianZaoHandler(item, data, device);
                        break;
                    case "武汉城建集团工程管理平台" :
                        chengJianHandler(item, data, device, datapushDTO);
                        break;
                    default:
                        break;
                }
            }
        }

//        Device device = new Device();
//        device.setCode(datapushDTO.getDevice_id());
//        List<Device> deviceList = deviceService.selectDevices(device);
//        if (deviceList == null || deviceList.size() == 0) {
//            return;
//        }
//
//        device = deviceList.get(0);


    }

    /**
     * 建设厅
     * @param docking
     * @param data
     * @param device
     */
    public void jianSheTingHandler(SystemDocking docking, JSONObject data,Device device) {

        List<SystemDockDevice> dockDeviceList = docking.getSystemDockDeviceList();
        if (dockDeviceList == null || dockDeviceList.size() == 0) {
            log.info("pushToSystemDockHandler未获取到需实时上传数据的设备绑定");
            return;
        }

        SystemDockDevice dockDevice = dockDeviceList.get(0);
        Integer type = dockDevice.getType();
        DockPushDTo dto = new DockPushDTo();

        // 塔吊的为driver_name，升降机为driver_name1
        String driver_name = data.getString("driver_name1");
        if (driver_name == null) {
            driver_name = data.getString("driver_name");
        }
        String id_card = data.getString("id_card");

        // 如无司机信息，未避免设备流水无法上传，填充字符串。
        dto.setDriverName(StringUtils.isBlank(driver_name) ? "无" : driver_name);
        try {
            // (秘钥secret太长了，JDK受版本安全限制，默认只允许128位长度以内的秘钥长度，如果密钥大于128，会抛异常)
            // 如这里加密报错，需要替换java-home路径下jre/bin/security/policy目录下两个jar包
            // AESUtil.removeCryptographyRestrictions();// 某些版本jdk可能会报错
            dto.setIdcardNumber(AESUtil.encryptCBC(StringUtils.isBlank(id_card) ? "无" : id_card, docking.getSecret()));
            dto.setDeviceNo(device.getCode());
            // 是否应该从电子档案关联司机信息
            // StringUtils.isNotBlank(driver_name) && StringUtils.isNotBlank(id_card) &&
            if (type == 1 || type == 2) {
                // 进行司机信息上传
                driverInfoPush(dto, docking, type);
            }

            String url = "";
            dto.setRecordTime(DateUtil.getDate());

            switch (type) {

                case 0:
                    // 扬尘设备
                    dto.setPm25(getDoubleNotNull(data.getDouble("pm25")));
                    dto.setPm10(getDoubleNotNull(data.getDouble("pm10")));
                    dto.setTsp(getDoubleNotNull(data.getDouble("tsp")));
                    dto.setNoise(getDoubleNotNull(data.getDouble("noise")));
                    dto.setNoise(getDoubleNotNull(data.getDouble("noise")));
                    dto.setWindSpeed(getDoubleNotNull(data.getDouble("ws")));
                    dto.setWindDirect(getDoubleNotNull(data.getDouble("wd360")));
                    dto.setWindPower(getDoubleNotNull(data.getDouble("wp")));
                    dto.setTemp(getDoubleNotNull(data.getDouble("tem")));
                    dto.setHumid(getDoubleNotNull(data.getDouble("hum")));
                    dto.setAtmosphere(getDoubleNotNull(data.getDouble("atm")));

                    url = "/api/device/data/environment";
                    break;

                case 1:
                    // 塔机设备流水上传
                    // 不知道对应哪个字段
                    dto.setLiftingCapacity(getDoubleNotNull(data.getDouble("weight")));
                    dto.setMomentForce(getDoubleNotNull(data.getDouble("torque")));
                    dto.setWindSpeed(getDoubleNotNull(data.getDouble("wind_speed")));// 风速
                    dto.setAmplitude(getDoubleNotNull(data.getDouble("range")));// 幅度
                    dto.setRound(getDoubleNotNull(data.getDouble("rotation")));// 回转
                    dto.setHeight(getDoubleNotNull(data.getDouble("height")));// 高度
                    dto.setAngleX(getDoubleNotNull(data.getDouble("tilt")));// 倾角
                    dto.setAngleY(getDoubleNotNull(data.getDouble("tilt")));// 倾角

                    url = "/api/device/data/towerCrane";

                    break;

                case 2:
                    // 升降机设备
                    dto.setCurrentLoad(getDoubleNotNull(data.getDouble("weight")));// 载重
                    dto.setSpeed(getDoubleNotNull(data.getDouble("speed")));// 速度 单位：m/s
                    dto.setHeight(getDoubleNotNull(data.getDouble("height")));// 高度
                    dto.setAngleY(getDoubleNotNull(data.getDouble("tilt_y")));// 倾角
                    dto.setAngleX(getDoubleNotNull(data.getDouble("tilt_x")));// 倾角
                    dto.setFrontLockState(getIntNotNull(data.getInteger("front_door")));
                    dto.setBackLockState(getIntNotNull(data.getInteger("after_door")));
                    //物模型中门锁告警为0是正常1是告警，市政平台对接文档为0是告警1是正常，所以这里取反，建设厅暂时不知，先注释
//                    dto.setFrontLockState(Math.abs(getIntNotNull(data.getInteger("door_alarm_state"))-1));
//                    dto.setBackLockState(Math.abs(getIntNotNull(data.getInteger("door_alarm_state"))-1));
                    url = "/api/device/data/elevator";
                    break;

                case 3:
                    // 视频流水需要定期重新注册更新通道号和token
                    RaiseDustDTO one = new RaiseDustDTO();
                    one.setDeviceName(device.getName());// 设备名称
                    one.setDeviceNo(device.getCode());// 设备编号
                    one.setDeviceModel(device.getDeviceUnitCode());// 设备型号
                    one.setDeviceCategory(device.getDeviceTypeName());// 设备类型
                    one.setPositionType("007");// 目前设备信息与部位信息未能完全匹配，先设置为其他部位007
                    one.setMonitorPlace(StringUtils.isBlank(device.getSite()) ? "暂无" : device.getSite());// 安装位置

                    String ezopen = data.getString("ezopen");
                    String accessToken = data.getString("accessToken");

                    // List<DeviceAttributeStatus> deviceAttributeStatus =
                    // getDeviceAttributeStatus(device);
                    // Map<String, Object> map = deviceAttributeStatus.stream().collect(
                    // Collectors.toMap(DeviceAttributeStatus::getPropCode,
                    // DeviceAttributeStatus::getPropValue));

                    String videoUrl = String.format(
                            "https://open.ys7.com/ezopen/h5/iframe?bSupporDoubleClickFull=0&url=%s&autoplay=1&audio=1&accessToken=%s&templete=1&id=video0&decoderVersion=",
                            ezopen, accessToken);

                    one.setVideoStreamUrl(videoUrl);

                    dto.setRaiseDustDTO(one);
                    url = "/api/device/register/video";

                    break;

                default:
                    break;
            }

            if (StringUtils.isNotBlank(url)) {
                String tempSystemPushUrl;
                if(StringUtils.isNotEmpty(docking.getUrl())){
                    tempSystemPushUrl = docking.getUrl();
                } else {
                    tempSystemPushUrl = systemPushUrl;
                }
                log.info("系统对接：开始同步设备流水数据到（湖北省建设厅智慧工地管理平台）-----");
                String respData = DeviceInfoPostUtil.handleData(docking.getAppid(), docking.getSecret(),
                        JSONObject.toJSONString(dto), tempSystemPushUrl + url);

                //saveInfo(systemPushUrl + url, respData, JSONObject.toJSONString(dto));
            }

        } catch (Exception e) {

            log.error("pushToSystemDockHandler error:{}", e.getMessage());
        }
    }

//    public static void main(String[] args) {
//        String regex = "^(\\d{6})(19|20)(\\d{2})(0[1-9]|1[0-2])(0[1-9]|[1-2]\\d|3[0-1])(\\d{3})([0-9Xx])$";
//        System.out.println(Pattern.matches(regex, "001081199001011234"));
//    }

    /**
     * 房屋市政
     * @param docking
     * @param device
     */
    public void fangWuShiZhengHandler(SystemDocking docking, JSONObject data,Device device) {
        List<SystemDockDevice> dockDeviceList = docking.getSystemDockDeviceList();
        if (dockDeviceList == null || dockDeviceList.size() == 0) {
            log.info("pushToSystemDockHandler未获取到需实时上传数据的设备绑定");
            return;
        }

        SystemDockDevice dockDevice = dockDeviceList.get(0);
        Integer type = dockDevice.getType();
        DockPushDTo dto = new DockPushDTo();

        // 塔吊的为driver_name，升降机为driver_name1
        String driver_name = data.getString("driver_name1");
        if (driver_name == null) {
            driver_name = data.getString("driver_name");
        }
        String id_card = data.getString("id_card");


        try {
            // (秘钥secret太长了，JDK受版本安全限制，默认只允许128位长度以内的秘钥长度，如果密钥大于128，会抛异常)
            // 如这里加密报错，需要替换java-home路径下jre/bin/security/policy目录下两个jar包
            // AESUtil.removeCryptographyRestrictions();// 某些版本jdk可能会报错
            String regex = "^(\\d{6})(19|20)(\\d{2})(0[1-9]|1[0-2])(0[1-9]|[1-2]\\d|3[0-1])(\\d{3})([0-9Xx])$";
            // 如无司机信息，传一个默认的人与身份证
            dto.setDriverName(ObjectUtils.isEmpty(driver_name) ? "江峰" : driver_name);
            if (ObjectUtils.isEmpty(id_card)) {
                dto.setIdcardNumber(AESUtil.encryptCBC("42011719921123431X", docking.getSecret()));
            } else if(!Pattern.matches(regex, id_card)){ //如果不是身份证账号
                dto.setDriverName("江峰");
                dto.setIdcardNumber(AESUtil.encryptCBC("42011719921123431X", docking.getSecret()));
            } else {
                dto.setIdcardNumber(AESUtil.encryptCBC(id_card, docking.getSecret()));
            }

            dto.setDeviceNo(device.getCode());
            String url = "";
            dto.setRecordTime(DateUtil.getDate());

            switch (type) {

                case 0:
                    // 扬尘设备
                    dto.setPm25(getDoubleNotNull(data.getDouble("pm25")));
                    dto.setPm10(getDoubleNotNull(data.getDouble("pm10")));
                    dto.setTsp(getDoubleNotNull(data.getDouble("tsp")));
                    dto.setNoise(getDoubleNotNull(data.getDouble("noise")));
                    dto.setNoise(getDoubleNotNull(data.getDouble("noise")));
                    dto.setWindSpeed(getDoubleNotNull(data.getDouble("ws")));
                    dto.setWindDirect(getDoubleNotNull(data.getDouble("wd360")));
                    dto.setWindPower(getDoubleNotNull(data.getDouble("wp")));
                    dto.setTemp(getDoubleNotNull(data.getDouble("tem")));
                    dto.setHumid(getDoubleNotNull(data.getDouble("hum")));
                    dto.setAtmosphere(getDoubleNotNull(data.getDouble("atm")));

                    url = "/api/device/data/environment";
                    break;

                case 1:
                    // 塔机设备流水上传
                    // 不知道对应哪个字段
                    dto.setLiftingCapacity(getDoubleNotNull(data.getDouble("weight")));
                    dto.setMomentForce(getDoubleNotNull(data.getDouble("torque")));
                    dto.setWindSpeed(getDoubleNotNull(data.getDouble("wind_speed")));// 风速
                    dto.setAmplitude(getDoubleNotNull(data.getDouble("range")));// 幅度
                    dto.setRound(getDoubleNotNull(data.getDouble("rotation")));// 回转
                    dto.setHeight(getDoubleNotNull(data.getDouble("height")));// 高度
                    dto.setAngleX(getDoubleNotNull(data.getDouble("tilt")));// 倾角
                    dto.setAngleY(getDoubleNotNull(data.getDouble("tilt")));// 倾角

                    url = "/api/device/data/towerCrane";

                    break;

                case 2:
                    // 升降机设备
                    dto.setCurrentLoad(getDoubleNotNull(data.getDouble("weight")));// 载重
                    dto.setSpeed(getDoubleNotNull(data.getDouble("speed")));// 速度 单位：m/s
                    dto.setHeight(getDoubleNotNull(data.getDouble("height")));// 高度
                    dto.setAngleY(getDoubleNotNull(data.getDouble("tilt_y")));// 倾角
                    dto.setAngleX(getDoubleNotNull(data.getDouble("tilt_x")));// 倾角
//                    dto.setFrontLockState(getIntNotNull(data.getInteger("front_door")));
//                    dto.setBackLockState(getIntNotNull(data.getInteger("after_door")));
                    //物模型中门锁告警为0是正常1是告警，市政平台对接文档为0是告警1是正常，所以这里取反
                    dto.setFrontLockState(Math.abs(getIntNotNull(data.getInteger("door_alarm_state"))-1));
                    dto.setBackLockState(Math.abs(getIntNotNull(data.getInteger("door_alarm_state"))-1));
                    url = "/api/device/data/elevator";
                    break;

                case 3:
                    // 视频流水需要定期重新注册更新通道号和token
                    RaiseDustDTO one = new RaiseDustDTO();
                    one.setDeviceName(device.getName());// 设备名称
                    one.setDeviceNo(device.getCode());// 设备编号
                    one.setDeviceModel(device.getDeviceUnitCode());// 设备型号
                    one.setDeviceCategory(device.getDeviceTypeName());// 设备类型
                    one.setPositionType("007");// 目前设备信息与部位信息未能完全匹配，先设置为其他部位007
                    one.setMonitorPlace(StringUtils.isBlank(device.getSite()) ? "暂无" : device.getSite());// 安装位置

                    String ezopen = data.getString("ezopen");
                    String accessToken = data.getString("accessToken");

                    // List<DeviceAttributeStatus> deviceAttributeStatus =
                    // getDeviceAttributeStatus(device);
                    // Map<String, Object> map = deviceAttributeStatus.stream().collect(
                    // Collectors.toMap(DeviceAttributeStatus::getPropCode,
                    // DeviceAttributeStatus::getPropValue));

                    String videoUrl = String.format(
                            "https://open.ys7.com/ezopen/h5/iframe?bSupporDoubleClickFull=0&url=%s&autoplay=1&audio=1&accessToken=%s&templete=1&id=video0&decoderVersion=",
                            ezopen, accessToken);

                    one.setVideoStreamUrl(videoUrl);

                    dto.setRaiseDustDTO(one);
                    url = "/api/device/register/video";

                    break;

                default:
                    break;
            }

            if (StringUtils.isNotBlank(url)) {
                String tempSystemPushUrl;
                if(StringUtils.isNotEmpty(docking.getUrl())){
                    tempSystemPushUrl = docking.getUrl();
                } else {
                    tempSystemPushUrl = systemPushUrl;
                }
                // 临时：先调设备心跳接口模拟在线
                SystemDockServerDTO systemDockServerDTO = new SystemDockServerDTO();
                systemDockServerDTO.setDeviceNo(device.getCode());
                switch (type)
                {
                    case 0:
                        systemDockServerDTO.setDeviceType(1);
                        break;
                    case 1:
                        systemDockServerDTO.setDeviceType(2);
                        break;
                    case 2:
                        systemDockServerDTO.setDeviceType(3);
                        break;
                    default:
                        break;
                }

                if(systemDockServerDTO.getDeviceType()!=null) {
                    // 先调设备连接心跳
                    String serverUrl = "/api/device/getServer";
                    String serverData = JSONObject.toJSONString(systemDockServerDTO);
                    log.info("系统对接：心跳日志----武汉市房屋市政工程智慧工地管理平台-----");
                    DeviceInfoPostUtil.handleData(docking.getAppid(), docking.getSecret(), serverData,
                            tempSystemPushUrl + serverUrl);
                }

                log.info("系统对接：开始同步设备流水数据到（武汉市房屋市政工程智慧工地管理平台）-----");
                String respData = DeviceInfoPostUtil.handleData(docking.getAppid(), docking.getSecret(),
                        JSONObject.toJSONString(dto), tempSystemPushUrl + url);

                //saveInfo(systemPushUrl + url, respData, JSONObject.toJSONString(dto));
            }

        } catch (Exception e) {

            log.error("pushToSystemDockHandler error:{}", e.getMessage());
        }
    }

    /**
     * 东湖高新
     * @param docking
     * @param device
     */
    public void dongHuGaoXinHandler(SystemDocking docking, JSONObject data,Device device) {
        List<SystemDockDevice> dockDeviceList = docking.getSystemDockDeviceList();
        if (dockDeviceList == null || dockDeviceList.size() == 0) {
            log.info("pushToSystemDockHandler未获取到需实时上传数据的设备绑定");
            return;
        }

        SystemDockDevice dockDevice = dockDeviceList.get(0);
        Integer type = dockDevice.getType();
        DockPushDTo dto = new DockPushDTo();

        // 塔吊的为driver_name，升降机为driver_name1
        String driver_name = data.getString("driver_name1");
        if (driver_name == null) {
            driver_name = data.getString("driver_name");
        }
        String id_card = data.getString("id_card");


        try {
            // (秘钥secret太长了，JDK受版本安全限制，默认只允许128位长度以内的秘钥长度，如果密钥大于128，会抛异常)
            // 如这里加密报错，需要替换java-home路径下jre/bin/security/policy目录下两个jar包
            // AESUtil.removeCryptographyRestrictions();// 某些版本jdk可能会报错
            String regex = "^(\\d{6})(19|20)(\\d{2})(0[1-9]|1[0-2])(0[1-9]|[1-2]\\d|3[0-1])(\\d{3})([0-9Xx])$";
            // 如无司机信息，传一个默认的人与身份证
            dto.setDriverName(ObjectUtils.isEmpty(driver_name) ? "江峰" : driver_name);
            if (ObjectUtils.isEmpty(id_card)) {
                dto.setIdcardNumber(AESUtil.encryptCBC("42011719921123431X", docking.getSecret()));
            } else if(!Pattern.matches(regex, id_card)){ //如果不是身份证账号
                dto.setDriverName("江峰");
                dto.setIdcardNumber(AESUtil.encryptCBC("42011719921123431X", docking.getSecret()));
            } else {
                dto.setIdcardNumber(AESUtil.encryptCBC(id_card, docking.getSecret()));
            }

            dto.setDeviceNo(device.getCode());
            String url = "";
            dto.setRecordTime(DateUtil.getDate());

            switch (type) {

                case 0:
                    // 扬尘设备
                    dto.setPm25(getDoubleNotNull(data.getDouble("pm25")));
                    dto.setPm10(getDoubleNotNull(data.getDouble("pm10")));
                    dto.setTsp(getDoubleNotNull(data.getDouble("tsp")));
                    dto.setNoise(getDoubleNotNull(data.getDouble("noise")));
                    dto.setNoise(getDoubleNotNull(data.getDouble("noise")));
                    dto.setWindSpeed(getDoubleNotNull(data.getDouble("ws")));
                    dto.setWindDirect(getDoubleNotNull(data.getDouble("wd360")));
                    dto.setWindPower(getDoubleNotNull(data.getDouble("wp")));
                    dto.setTemp(getDoubleNotNull(data.getDouble("tem")));
                    dto.setHumid(getDoubleNotNull(data.getDouble("hum")));
                    dto.setAtmosphere(getDoubleNotNull(data.getDouble("atm")));

                    url = "/api/device/data/environment";
                    break;

                case 1:
                    // 塔机设备流水上传
                    // 不知道对应哪个字段
                    dto.setLiftingCapacity(getDoubleNotNull(data.getDouble("weight")));
                    dto.setMomentForce(getDoubleNotNull(data.getDouble("torque")));
                    dto.setWindSpeed(getDoubleNotNull(data.getDouble("wind_speed")));// 风速
                    dto.setAmplitude(getDoubleNotNull(data.getDouble("range")));// 幅度
                    dto.setRound(getDoubleNotNull(data.getDouble("rotation")));// 回转
                    dto.setHeight(getDoubleNotNull(data.getDouble("height")));// 高度
                    dto.setAngleX(getDoubleNotNull(data.getDouble("tilt")));// 倾角
                    dto.setAngleY(getDoubleNotNull(data.getDouble("tilt")));// 倾角

                    url = "/api/device/data/towerCrane";

                    break;

                case 2:
                    // 升降机设备
                    dto.setCurrentLoad(getDoubleNotNull(data.getDouble("weight")));// 载重
                    dto.setSpeed(getDoubleNotNull(data.getDouble("speed")));// 速度 单位：m/s
                    dto.setHeight(getDoubleNotNull(data.getDouble("height")));// 高度
                    dto.setAngleY(getDoubleNotNull(data.getDouble("tilt_y")));// 倾角
                    dto.setAngleX(getDoubleNotNull(data.getDouble("tilt_x")));// 倾角
                    dto.setFrontLockState(getIntNotNull(data.getInteger("front_door")));
                    dto.setBackLockState(getIntNotNull(data.getInteger("after_door")));
                    //物模型中门锁告警为0是正常1是告警，市政平台对接文档为0是告警1是正常，所以这里取反，东湖高新接口暂时不止，先注释
//                    dto.setFrontLockState(Math.abs(getIntNotNull(data.getInteger("door_alarm_state"))-1));
//                    dto.setBackLockState(Math.abs(getIntNotNull(data.getInteger("door_alarm_state"))-1));

                    url = "/api/device/data/elevator";
                    break;

                case 3:
                    // 视频流水需要定期重新注册更新通道号和token
                    RaiseDustDTO one = new RaiseDustDTO();
                    one.setDeviceName(device.getName());// 设备名称
                    one.setDeviceNo(device.getCode());// 设备编号
                    one.setDeviceModel(device.getDeviceUnitCode());// 设备型号
                    one.setDeviceCategory(device.getDeviceTypeName());// 设备类型
                    one.setPositionType("007");// 目前设备信息与部位信息未能完全匹配，先设置为其他部位007
                    one.setMonitorPlace(StringUtils.isBlank(device.getSite()) ? "暂无" : device.getSite());// 安装位置

                    String ezopen = data.getString("ezopen");
                    String accessToken = data.getString("accessToken");

                    // List<DeviceAttributeStatus> deviceAttributeStatus =
                    // getDeviceAttributeStatus(device);
                    // Map<String, Object> map = deviceAttributeStatus.stream().collect(
                    // Collectors.toMap(DeviceAttributeStatus::getPropCode,
                    // DeviceAttributeStatus::getPropValue));

                    String videoUrl = String.format(
                            "https://open.ys7.com/ezopen/h5/iframe?bSupporDoubleClickFull=0&url=%s&autoplay=1&audio=1&accessToken=%s&templete=1&id=video0&decoderVersion=",
                            ezopen, accessToken);

                    one.setVideoStreamUrl(videoUrl);

                    dto.setRaiseDustDTO(one);
                    url = "/api/device/register/video";

                    break;

                default:
                    break;
            }

            if (StringUtils.isNotBlank(url)) {
                String tempSystemPushUrl;
                if(StringUtils.isNotEmpty(docking.getUrl())){
                    tempSystemPushUrl = docking.getUrl();
                } else {
                    tempSystemPushUrl = systemPushUrl;
                }
                // 临时：先调设备心跳接口模拟在线
//                SystemDockServerDTO systemDockServerDTO = new SystemDockServerDTO();
//                systemDockServerDTO.setDeviceNo(device.getCode());
//                switch (type)
//                {
//                    case 0:
//                        systemDockServerDTO.setDeviceType(1);
//                        break;
//                    case 1:
//                        systemDockServerDTO.setDeviceType(2);
//                        break;
//                    case 2:
//                        systemDockServerDTO.setDeviceType(3);
//                        break;
//                    default:
//                        break;
//                }
//
//                if(systemDockServerDTO.getDeviceType()!=null) {
//                    // 先调设备连接心跳
//                    String serverUrl = "/api/device/getServer";
//                    String serverData = JSONObject.toJSONString(systemDockServerDTO);
//                    log.info("系统对接：心跳日志----武汉市东湖高新区智慧工地管理平台-----");
//                    DeviceInfoPostUtil.handleData(docking.getAppid(), docking.getSecret(), serverData,
//                            tempSystemPushUrl + serverUrl);
//                }

                log.info("系统对接：开始同步设备流水数据到（武汉市东湖高新区智慧工地管理平台）-----");
                String respData = DeviceInfoPostUtil.handleData(docking.getAppid(), docking.getSecret(),
                        JSONObject.toJSONString(dto), tempSystemPushUrl + url);

                //saveInfo(systemPushUrl + url, respData, JSONObject.toJSONString(dto));
            }

        } catch (Exception e) {

            log.error("pushToSystemDockHandler error:{}", e.getMessage());
        }
    }

    /**
     * 光谷文化中心智慧建造云平台
     * @param docking
     * @param device
     */
    public void zhiHuiJianZaoHandler(SystemDocking docking, JSONObject data,Device device) {
        List<SystemDockDevice> dockDeviceList = docking.getSystemDockDeviceList();
        if (dockDeviceList == null || dockDeviceList.size() == 0) {
            log.info("pushToSystemDockHandler未获取到需实时上传数据的设备绑定");
            return;
        }
        // 有且只有一条设备信息
        SystemDockDevice dockDevice = dockDeviceList.get(0);
        Integer type = dockDevice.getType();
        DockPushProDTO dto = new DockPushProDTO();

        // 塔吊的为driver_name，升降机为driver_name1
        String driver_name = data.getString("driver_name1");
        if (driver_name == null) {
            driver_name = data.getString("driver_name");
        }
        String id_card = data.getString("id_card");


        try {
            dto.setDeviceCode(device.getCode());
            dto.setProjUid(projUid);
            String url = "";
//            dto.setRecordTime(DateUtil.getDate());

            switch (type) {

                case 0:
                    // 扬尘设备
                    dto.setPm25(getDoubleNotNull(data.getDouble("pm25")));
                    dto.setPm10(getDoubleNotNull(data.getDouble("pm10")));
                    dto.setTsp(getDoubleNotNull(data.getDouble("tsp")));
                    dto.setNoise(getDoubleNotNull(data.getDouble("noise")));
                    dto.setTemp(getDoubleNotNull(data.getDouble("tem")));
                    dto.setHum(getDoubleNotNull(data.getDouble("hum")));
                    dto.setBp(getDoubleNotNull(data.getDouble("atm")));
                    dto.setWs(getDoubleNotNull(data.getDouble("ws")));
                    dto.setWd(getDoubleNotNull(data.getDouble("wd360")));
//                    dto.setWindPower(getDoubleNotNull(data.getDouble("wp")));

                    url = "/open_v1/modules/dust/records";
                    break;

                case 1:
                    // 塔机设备流水上传
                    dto.setScope(StringUtils.isBlank(data.getString("range")) ? "0" : data.getString("range"));// 幅度
                    dto.setHeight(StringUtils.isBlank(data.getString("height")) ? "0" : data.getString("height"));// 高度
                    dto.setRotate(StringUtils.isBlank(data.getString("rotation")) ? "0" : data.getString("rotation"));// 回转
                    dto.setOblique(StringUtils.isBlank(data.getString("tilt")) ? "0" : data.getString("tilt"));// 倾角
                    dto.setWs(getDoubleNotNull(data.getDouble("wind_speed")));// 风速
                    dto.setRated_weight("0");// 额定吊重
                    dto.setMomper(StringUtils.isBlank(data.getString("torque")) ? "0" : String.valueOf((int) (data.getDouble("torque") * 100))); // 力矩比
                    dto.setWeight(StringUtils.isBlank(data.getString("weight")) ? "0" : data.getString("weight")); // 吊重重量
                    dto.setState(0);// 状态

                    // 司机信息
                    // (秘钥secret太长了，JDK受版本安全限制，默认只允许128位长度以内的秘钥长度，如果密钥大于128，会抛异常)
                    // 如这里加密报错，需要替换java-home路径下jre/bin/security/policy目录下两个jar包
                    // AESUtil.removeCryptographyRestrictions();// 某些版本jdk可能会报错
                    String regex = "^(\\d{6})(19|20)(\\d{2})(0[1-9]|1[0-2])(0[1-9]|[1-2]\\d|3[0-1])(\\d{3})([0-9Xx])$";
                    // 如无司机信息，传一个默认的人与身份证
                    dto.setDricerName(ObjectUtils.isEmpty(driver_name) ? "江峰" : driver_name);
                    if (ObjectUtils.isEmpty(id_card)) {
                        dto.setIdcardnumber("42011719921123431X");
                    } else if(!Pattern.matches(regex, id_card)){ //如果不是身份证账号
                        dto.setDricerName("江峰");
                        dto.setIdcardnumber("42011719921123431X");
                    } else {
                        dto.setIdcardnumber(id_card);
                    }
                    dto.setStatus("1");
                    dto.setScore("0");
                    dto.setImg("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");

                    String driverUrl = "/api_v1/iot/add";
                    String tempSystemPushUrl;
                    if(StringUtils.isNotEmpty(docking.getUrl())){
                        tempSystemPushUrl = docking.getUrl();
                    } else {
                        tempSystemPushUrl = systemPushUrl;
                    }

                    log.info("系统对接：开始同步设备流水数据到（武汉市房屋市政工程智慧工地管理平台）-----");
                    String respData = DeviceInfoPostUtil.handleData2(JSONObject.toJSONString(dto), tempSystemPushUrl + driverUrl);
                    url = "/open_v1/modules/towerCrane/realTime";
                    dto.setDricerName(null);
                    dto.setIdcardnumber(null);
                    dto.setImg(null);
                    break;
                case 2:
                    // 升降机设备
                    dto.setWeight(StringUtils.isBlank(data.getString("weight")) ? "0" : data.getString("weight"));// 载重
                    dto.setHeight(StringUtils.isBlank(data.getString("height")) ? "0" : data.getString("height"));// 高度
                    dto.setSpeed(StringUtils.isBlank(data.getString("speed")) ? "0" : data.getString("speed"));// 速度 单位：m/s
                    dto.setFontDoorStatus(getIntNotNull(data.getInteger("front_door")));
                    dto.setBackDoorStatus(getIntNotNull(data.getInteger("after_door")));
                    if (data.getString("weight_alarm_state") != null && "1".equals(data.getString("weight_alarm_state"))) {
                        dto.setState(1);
                    } else if (data.getString("height_alarm_state") != null && "1".equals(data.getString("height_alarm_state"))) {
                        dto.setState(2);
                    } else if (data.getString("speed_alarm_state") != null && "1".equals(data.getString("speed_alarm_state"))) {
                        dto.setState(3);
                    } else if (data.getString("door_alarm_state") != null && "1".equals(data.getString("door_alarm_state"))) {
                        dto.setState(4);
                    } else {
                        dto.setState(0);
                    }
//                    dto.setAngleY(getDoubleNotNull(data.getDouble("tilt_y")));// 倾角
//                    dto.setAngleX(getDoubleNotNull(data.getDouble("tilt_x")));// 倾角

                    url = "/api_v1/modules/elevator/addElevatordata";
                    break;
                case 3:
                    // 视频流水需要定期重新注册更新通道号和token
                    dto.setType("3");
                    dto.setTitle(device.getName());
                    dto.setEnable("1");
                    String ezopen = data.getString("ezopen");
                    String accessToken = data.getString("accessToken");
                    String videoUrl = String.format(
                            "https://open.ys7.com/ezopen/h5/iframe?bSupporDoubleClickFull=0&url=%s&autoplay=1&audio=1&accessToken=%s&templete=1&id=video0&decoderVersion=",
                            ezopen, accessToken);
                    dto.setIp(videoUrl);
                    url = "/apple/saveVideAPi";
                    break;
                case 4:
                    // 水电表
                    dto.setDeviceCode(null);
                    dto.setDeviceNo(device.getCode());
                    dto.setTotalPower(data.getString("combined_active_energy"));
                    url = "/group/iot/push/water/electricity";
                    break;
                default:
                    break;
            }

            if (StringUtils.isNotBlank(url)) {
                String tempSystemPushUrl;
                if(StringUtils.isNotEmpty(docking.getUrl())){
                    tempSystemPushUrl = docking.getUrl();
                } else {
                    tempSystemPushUrl = systemPushUrl;
                }

                log.info("系统对接：开始同步设备流水数据到（光谷文化中心智慧建造云平台）-----");
                String respData = DeviceInfoPostUtil.handleData2(JSONObject.toJSONString(dto), tempSystemPushUrl + url);
            }

        } catch (Exception e) {

            log.error("pushToSystemDockHandler error:{}", e.getMessage());
        }
    }

    /**
     * 武汉城建集团工程管理平台
     * @param docking
     * @param device
     */
    public void chengJianHandler(SystemDocking docking, JSONObject data, Device device, DatapushDTO datapushDTO) {
        List<SystemDockDevice> dockDeviceList = docking.getSystemDockDeviceList();
        if (dockDeviceList == null || dockDeviceList.size() == 0) {
            log.info("pushToSystemDockHandler未获取到需实时上传数据的设备绑定");
            return;
        }
        // 有且只有一条设备信息
        SystemDockDevice dockDevice = dockDeviceList.get(0);
        Integer type = dockDevice.getType();
        DockPushProDTO dto = new DockPushProDTO();

        // 塔吊的为driver_name，升降机为driver_name1
        String driver_name = data.getString("driver_name1");
        if (driver_name == null) {
            driver_name = data.getString("driver_name");
        }
        String id_card = data.getString("id_card");


        try {
            dto.setTraceId(datapushDTO.getUuid());
            dto.setDeviceNumber(device.getCode());
            // 项目编码
            dto.setProjectNumber(docking.getAppid());
            String url = "";
            String deviceName = "";
            // 查询设备名称
            List<Device> deviceList = deviceService.selectDevicesPage(new Page<>(-1, -1), new Device().setCode(device.getCode())).getRecords();
            if (CollectionUtil.isNotEmpty(deviceList)) {
                deviceName = deviceList.get(0).getName();
            }
            dto.setDeviceName(deviceName);

            switch (type) {

                case 0:
                    // 扬尘设备
                    dto.setPm25(getDoubleNotNull(data.getDouble("pm25")));
                    dto.setPm10(getDoubleNotNull(data.getDouble("pm10")));
                    dto.setTsp(getDoubleNotNull(data.getDouble("tsp")));
                    dto.setNoise(getDoubleNotNull(data.getDouble("noise")));
                    dto.setTemp(getDoubleNotNull(data.getDouble("tem")));
                    dto.setHum(getDoubleNotNull(data.getDouble("hum")));
                    dto.setBp(getDoubleNotNull(data.getDouble("atm")));
                    dto.setWs(getDoubleNotNull(data.getDouble("ws")));
                    dto.setWd(getDoubleNotNull(data.getDouble("wd360")));
                    dto.setWp(getDoubleNotNull(data.getDouble("wp")));

                    url = "/applyapi/syncDust";
                    break;
                case 3:
                    // 摄像机
                    dto.setDeviceTypeName(datapushDTO.getDevice_unit());
                    // 视频流水需要定期重新注册更新通道号和token
                    String ezopen = data.getString("ezopen");
                    String accessToken = data.getString("accessToken");
                    String videoUrl = String.format(
                            "https://open.ys7.com/ezopen/h5/iframe?bSupporDoubleClickFull=0&url=%s&autoplay=1&audio=1&accessToken=%s&templete=1&id=video0&decoderVersion=",
                            ezopen, accessToken);
                    dto.setUrl(videoUrl);
                    url = "/applyapi/syncVideo";
                    break;
                case 5:
                    // 面板机
                    String cardOrGateId = data.getString("personId");
                    Gate gate = null;
                    // 获取用户身份证号码以及电话号码
                    if (StringUtils.isNotBlank(cardOrGateId)) {
                        List<UserProjectDTO> userProjectDTOS;
                        //先判断是否是自定义的id
                        if (cardOrGateId.startsWith(Gate.getIdPre())) {
                            String userId = cardOrGateId.replaceAll(Gate.getIdPre(), "");
                            userProjectDTOS = userProjectMapper.findByGateLinkId(Integer.valueOf(userId));
                        } else {
                            userProjectDTOS = userProjectMapper.findByCardOrGateId(cardOrGateId);
                        }
                        if (userProjectDTOS.size() > 0) {
                            UserProjectDTO userProjectDTO;
                            QueryWrapper<Gate> queryWrapper = new QueryWrapper<>();
                            queryWrapper.eq("code_", device.getCode());
                            //多人在岗时通过闸机查人员，一人在岗人员tenantId设备编号查询闸机
                            if (userProjectDTOS.size() ==1){
                                userProjectDTO = userProjectDTOS.get(0);
                                queryWrapper.eq("tenant_id_",userProjectDTO.getTenantId());
                                //根据闸机tenantId区分人员
                                List<Gate> gates = gateMapper.selectList(queryWrapper);
                                if (null != gates && gates.size() > 0) {
                                    gate = gates.get(0);
                                }
                            } else {
                                //根据闸机tenantId区分人员
                                List<Gate> gates = gateMapper.selectList(queryWrapper);
                                Set<String> tIds = gates.stream().map(g -> g.getTenantId())
                                        .collect(Collectors.toSet());
                                List<UserProjectDTO> projectDTOS = userProjectDTOS.stream()
                                        .filter(u -> tIds.contains(u.getTenantId()))
                                        .collect(Collectors.toList());
                                if (projectDTOS.size() > 0) {
                                    userProjectDTO = projectDTOS.get(0);
                                } else {
                                    //万一取不到就随机取一个
                                    userProjectDTO = userProjectDTOS.get(0);
                                }
                                List<Gate> gateList = gates.stream()
                                        .filter(g -> userProjectDTO.getTenantId().equals(g.getTenantId()))
                                        .collect(Collectors.toList());
                                if (gateList.size() > 0){
                                    gate = gateList.get(0);
                                }
                            }
                            // 手机号以及电话号码
                            dto.setUserNumber(userProjectDTO.getCard());
                            dto.setMobile(userProjectDTO.getTelephone());
                            // 闸机方向
                            if (gate != null) {
                                dto.setDirection(gate.getDirection());
                            }
                        }
                    }
                    dto.setCheckinTime(data.getString("capTime"));
                    dto.setImage(data.getString("closeupPic"));

                    url = "/applyapi/syncGateFace";
                default:
                    break;
            }

            if (StringUtils.isNotBlank(url)) {
                String tempSystemPushUrl;
                if(StringUtils.isNotEmpty(docking.getUrl())) {
                    tempSystemPushUrl = docking.getUrl();
                } else {
                    tempSystemPushUrl = systemPushUrl;
                }

                log.info("系统对接：开始同步设备流水数据到（武汉城建集团工程管理平台）-----");
                String respData = DeviceInfoPostUtil.handleData3(docking.getSecret(), JSONObject.toJSONString(dto), tempSystemPushUrl + url);
            }

        } catch (Exception e) {

            log.error("pushToSystemDockHandler error:{}", e.getMessage());
        }
    }

    /**
     * 司机信息上传
     *
     * @param dto
     * @param docking
     * @param type
     */
    private void driverInfoPush(DockPushDTo dto, SystemDocking docking, int type) {

        String url = "";
        if (type == 1) {
            // 塔机司机
            url = "/api/device/driver/towerCrane";
        } else if (type == 2) {
            // 升降机
            url = "/api/device/driver/elevator";
        }
        String tempSystemPushUrl;
        if(StringUtils.isNotEmpty(docking.getUrl())){
            tempSystemPushUrl = docking.getUrl();
        } else {
            tempSystemPushUrl = systemPushUrl;
        }
        log.info("--开始上传司机信息----" + JSONObject.toJSONString(dto));
        String respData = DeviceInfoPostUtil.handleData(docking.getAppid(), docking.getSecret(),
                JSONObject.toJSONString(dto), tempSystemPushUrl + url);

        //saveInfo(systemPushUrl + url, respData, JSONObject.toJSONString(dto));
    }

    /**
     * @param url
     * @param respCode
     * @param data
     */
    private void saveInfo(String url, String respCode, String data) {

        SystemDockInfo info = new SystemDockInfo();

        info.setSysname("湖北省建设厅智慧工地管理平台");
        info.setUrl(url);
        info.setData(data.replace("\"raiseDustDTO\":{", "").replace("},", ","));
        info.setCode(respCode);
        info.setCreateTime(new Date());

        //infoMapper.insert(info);
    }

    private Double getDoubleNotNull(Object key) {

        if (key == null) {

            return 0d;
        }

        double doubleValue = 0d;

        try {
            doubleValue = new BigDecimal(key.toString()).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
        } catch (Exception e) {
            log.info(e.getMessage());
        }

        return doubleValue;
    }

    private Integer getIntNotNull(Integer key) {

        if (key == null) {

            return 0;
        }

        return key;
    }

    @Override
    public void pushToZhiHuiJianZaoHandler() {
        zhiHuiJianZaoShiMingZhiHandler();
    }

    //人员一次最大上报数量
    private static final Integer MAX_NUMBER = 50;

    private void zhiHuiJianZaoShiMingZhiHandler() {
        //参建单位接口
        String unitAddUrlPath = urlPrefix + "/api_v1/modules/issueinfo/unitAdd";

        //班组接口
        String groupAddUrlPath = urlPrefix + "/api_v1/modules/issueinfo/addTeamInfo";

        //人员接口
        String userAddUrlPath = urlPrefix + "/api_v1/modules/issueinfo/addWorkerInfo";

        //考勤接口
        String userClockAddUrlPath = urlPrefix + "/api_v1/modules/issueinfo/addPlatAttendanceInfo";

        /**
         * todo
         * 1.同步参建单位 down
         * 2.同步班组信息 doing
         * 3.同步人员信息
         * 4.同步考勤信息
         */
        LinkappUser currentUser = linkappUserContextProducer.getNotNullCurrent();

        //获取参建单位列表
        RequestModel<LaborCompanyProjectDTO> requestModel = new RequestModel<>();
        Page page = new Page<>();
        page.setSize(-1);
        requestModel.setPage(page);
        requestModel.setCustomQueryParams(new LaborCompanyProjectDTO());
        IPage<LaborCompanyProjectDTO> unitPage = laborCompanyProjectService.queryListByPage(requestModel);
        List<LaborCompanyProjectDTO> laborCompanyProjectDTOList = unitPage.getRecords();
        if (null == laborCompanyProjectDTOList) {
            return;
        }
        //循环上报参建单位-获取参建单位id-持久化存储id
        for (LaborCompanyProjectDTO laborCompanyProjectDTO : laborCompanyProjectDTOList) {
            DockParticipatingUnitsDTO dockParticipatingUnitsDTO = new DockParticipatingUnitsDTO();
            dockParticipatingUnitsDTO.setCreditunits(StringUtils.isBlank(laborCompanyProjectDTO.getCode()) ? laborCompanyProjectDTO.getCompanyProjectId() : laborCompanyProjectDTO.getCode());
            dockParticipatingUnitsDTO.setName(StringUtils.isBlank(laborCompanyProjectDTO.getName()) ? "blank" : laborCompanyProjectDTO.getName());
            dockParticipatingUnitsDTO.setAreaCode(StringUtils.isBlank(laborCompanyProjectDTO.getAddress()) ? "blank" : laborCompanyProjectDTO.getAddress());
            dockParticipatingUnitsDTO.setBuilderLicenses("blank");
            dockParticipatingUnitsDTO.setUnittype(unitTypeConverse(laborCompanyProjectDTO.getBuildType()));
            //发送post请求
            String unitResult = "";
            try {
                unitResult = HttpClientUtil.doPostApply(unitAddUrlPath, JSON.toJSONString(dockParticipatingUnitsDTO), projUid);
            } catch (Exception e) {
                e.printStackTrace();
            }
            JSONObject unitJsonObject = JSONObject.parseObject(unitResult);
            //第三方不存在该参建单位则返回其id
            if ("200".equals(unitJsonObject.get("code"))) {
                //从返回数据中获取id
                String unitId = (String) unitJsonObject.get("data");
                //持久化第三方id
                LaborCompanyProject laborCompanyProject = new LaborCompanyProject();
                laborCompanyProject.setId(laborCompanyProjectDTO.getCompanyProjectId());
                laborCompanyProject.setSysDockId(unitId);
                laborCompanyProjectService.updateById(laborCompanyProject);
            }
        }
        //遍历项目下所有参建单位，构建map为班组数据做准备
        Map<String, String> companyGroupIdMap = new HashMap<>();
        QueryWrapper unitQueryWrapper = new QueryWrapper();
        unitQueryWrapper.eq("tenant_id_", currentUser.getTenantId());
        List<LaborCompanyProject> laborCompanyProjectList = laborCompanyProjectService.list(unitQueryWrapper);
        for (LaborCompanyProject laborCompanyProject : laborCompanyProjectList) {
            String companyId = laborCompanyProject.getId();
            String dockId = laborCompanyProject.getSysDockId();
            if (StringUtils.isNotBlank(companyId) && StringUtils.isNotBlank(dockId)) {
                companyGroupIdMap.put(laborCompanyProject.getId(), laborCompanyProject.getSysDockId());
            }
        }

        //获取班组列表
        LaborCompanyGroupVo laborCompanyGroupVo = new LaborCompanyGroupVo();
        laborCompanyGroupVo.setLaborCompany(new LaborCompany());
        laborCompanyGroupVo.setLaborGroup(new Group());
        laborCompanyGroupVo.getLaborCompany().setTenantId(currentUser.getTenantId());
        laborCompanyGroupVo.getLaborGroup().setTenantId(currentUser.getTenantId());
        List<LaborCompanyGroupDto> laborCompanyGroupDtoList = companyMapper.selectCompanyGroupDtoList(laborCompanyGroupVo);
        //循环上报班组信息-获取班组id-持久化id
        for (LaborCompanyGroupDto laborCompanyGroupDto : laborCompanyGroupDtoList) {
            String company = companyGroupIdMap.get(laborCompanyGroupDto.getCompanyProjectId());
            String corpName = laborCompanyGroupDto.getName();
            String corpCode = laborCompanyGroupDto.getCode();
            for (Group group : laborCompanyGroupDto.getGroupList()) {
                DockGroupDTO dockGroupDTO = new DockGroupDTO(corpCode, corpName, group.getName(), company, group.getMainPeople());
                //发送post请求
                String groupResult = "";
                try {
                    groupResult = HttpClientUtil.doPostApply(groupAddUrlPath, JSON.toJSONString(dockGroupDTO), projUid);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                JSONObject groupJsonObject = JSONObject.parseObject(groupResult);
                //第三方不存在该班组则返回其id
                if ("200".equals(groupJsonObject.get("code"))) {
                    //从返回数据中获取id
                    String groupId = (String) groupJsonObject.get("data");
                    //持久化第三方id
                    Group group1 = new Group();
                    group1.setId(group.getId());
                    group1.setSysDockId(groupId);
                    groupService.updateById(group1);
                }
            }
        }
        //遍历项目下所有班组，构建map为人员数据做准备
        List<LaborCompanyGroupDto> laborCompanyGroupDtoList1 = companyMapper.selectCompanyGroupDtoList(laborCompanyGroupVo);
        Map<String, DockGroupExDTO> dockGroupMap = new HashMap<>();
        for (LaborCompanyGroupDto laborCompanyGroupDto : laborCompanyGroupDtoList1) {
            DockGroupExDTO dockGroupExDTO = new DockGroupExDTO();
            dockGroupExDTO.setCompany(companyGroupIdMap.get(laborCompanyGroupDto.getCompanyProjectId()));
            dockGroupExDTO.setCorpCode(laborCompanyGroupDto.getCode());
            dockGroupExDTO.setCorpName(laborCompanyGroupDto.getName());
            for (Group group : laborCompanyGroupDto.getGroupList()) {
                dockGroupExDTO.setTeamUid(group.getSysDockId());
                dockGroupExDTO.setTeamName(group.getName());
                dockGroupMap.put(group.getId(), dockGroupExDTO);
            }
        }

        //获取人员列表
        UserProjectVo userProjectVo = new UserProjectVo();
        UserProject uptmp = new UserProject();
        uptmp.setTenantId(currentUser.getTenantId());
        userProjectVo.setUserProject(uptmp);
        List<UserProjectDTO> userProjectDTOList = userProjectMapper.queryUserProjectDtoList1(userProjectVo);
        //按班组分组
        Map<String, List<UserProjectDTO>> groupMap = userProjectDTOList.stream().collect(Collectors.groupingBy(UserProjectDTO::getGroupId));
        //按班组循环上报人员信息
        groupMap.forEach((k, v) -> {
            //按照要求拆分list-每个小list不超过50条数据
            int limit = countStep(v.size());
            List<List<UserProjectDTO>> splitList = new ArrayList<>();
            Stream.iterate(0, n -> n + 1).limit(limit).forEach(i -> {
                splitList.add(v.stream().skip(i * MAX_NUMBER).limit(MAX_NUMBER).collect(Collectors.toList()));
            });
            //准备一个Map给后面更新userproject表使用map<身份证号，{userprojectid,username}>
            Map<String, UserProjectDTO> userProjectMap = new HashMap<>();
            for (List<UserProjectDTO> userProjectDTOS : splitList) {
                DockCompanyUserDTO dockCompanyUserDTO = new DockCompanyUserDTO();
                DockGroupExDTO test = dockGroupMap.get(k);
                if (test == null) {
                    break;
                }
                dockCompanyUserDTO.setCompany(dockGroupMap.get(k).getCompany());
                dockCompanyUserDTO.setCorpName(dockGroupMap.get(k).getCorpName());
                dockCompanyUserDTO.setCorpCode(dockGroupMap.get(k).getCorpCode());
                dockCompanyUserDTO.setTeamUid(dockGroupMap.get(k).getTeamUid());
                dockCompanyUserDTO.setTeamName(dockGroupMap.get(k).getTeamName());
                List<DockUserDTO> userDTOList = new ArrayList<>();
                for (UserProjectDTO userProjectDTO : userProjectDTOS) {
                    DockUserDTO dockUserDTO = dockUserProjectDTOToUser(userProjectDTO);
//                    //若人员信息已存在，则不加入datalist发送post请求
//                    if (StringUtils.isNotBlank(userProjectDTO.getSysDockId())) {
//                        break;
//                    }
                    userDTOList.add(dockUserDTO);
                    userProjectMap.put(userProjectDTO.getCard(), userProjectDTO);
                }
                dockCompanyUserDTO.setDataList(userDTOList);
                String strtest = JSON.toJSONString(dockCompanyUserDTO);
                //发送post请求
                String userResult = "";
                try {
                    userResult = HttpClientUtil.doPostApply(userAddUrlPath, JSON.toJSONString(dockCompanyUserDTO), projUid);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                //持久化存储第三方用户id
                JSONObject userJsonObject = JSONObject.parseObject(userResult);
                String tmp = userJsonObject.getString("isNull");
                JSONObject resultObject = JSONObject.parseObject(tmp);
                if ("200".equals(resultObject.getString("code"))) {
                    JSONArray userja = resultObject.getJSONArray("userData");
                    for (int i = 0; i < userja.size(); i++) {
                        JSONObject jo = userja.getJSONObject(i);
                        String idcard = jo.getString("身份证");
                        if (StringUtils.isBlank(idcard)) {
                            break;
                        }
                        UserProject userProject = new UserProject();
                        //身份证号为空
                        if (null == userProjectMap.get(idcard)) {
                            break;
                        }
                        userProject.setId(userProjectMap.get(idcard).getId());
                        userProject.setSysDockId(jo.getString(userProjectMap.get(idcard).getUserName()));
                        userProjectMapper.updateById(userProject);
                    }
                }
            }
        });
//        //遍历项目下所有班组所有人员，构建map为考勤数据做准备
//        List<UserProjectDTO> userProjectDTOListNew = userProjectMapper.queryUserProjectDtoList1(userProjectVo);
//        Map<String, DockUserDTO> dockUserExDTOMap = new HashMap<>();
//        for (UserProjectDTO userProjectDTO : userProjectDTOListNew) {
//            DockUserDTO dockUserDTO = dockUserProjectDTOToUser(userProjectDTO);
//            dockUserDTO.setWorkerUid(userProjectDTO.getSysDockId());
//            dockUserExDTOMap.put(userProjectDTO.getUserId(), dockUserDTO);
//        }
//
//        //获取闸机人员列表
//        List<UserClock> userClockList = userClockMapper.dockGetListByTenantId(currentUser.getTenantId());
//        //按闸机序列号分组
//        Map<String, List<UserClock>> userClockMap = userClockList.stream().filter(map -> map.getGateCode() != null).collect(Collectors.groupingBy(UserClock::getGateCode));
//        //循环上报考勤信息
//        userClockMap.forEach((k, v) -> {
//            //按照要求拆分list-每个小list不超过50条数据
//            int limit = countStep(v.size());
//            List<List<UserClock>> splitList = new ArrayList<>();
//            Stream.iterate(0, n -> n + 1).limit(limit).forEach(i -> {
//                splitList.add(v.stream().skip(i * MAX_NUMBER).limit(MAX_NUMBER).collect(Collectors.toList()));
//            });
//            //循环构建请求参数并发送请求
//            for (List<UserClock> userClocks : splitList) {
//                DockCompanyUserClockDTO dockCompanyUserClockDTO = new DockCompanyUserClockDTO();
//                dockCompanyUserClockDTO.setDeviceId(k);
//                List<DockUserClockDTO> dockUserClockDTOList = new ArrayList<>();
//                for (UserClock userClock : userClocks) {
//                    dockCompanyUserClockDTO.setCompany(companyGroupIdMap.get(userClock.getCompanyProjectId()));
//                    if (null == dockUserExDTOMap.get(userClock.getUserId())) {
//                        break;
//                    }
//                    DockUserClockDTO dockUserClockDTO = dockUserGateToUserClock(userClock, dockUserExDTOMap, dockGroupMap);
//                    dockUserClockDTOList.add(dockUserClockDTO);
//                }
//                dockCompanyUserClockDTO.setDataList(dockUserClockDTOList);
//                //发送post请求
//                try {
//                    HttpClientUtil.doPostApply(userClockAddUrlPath, JSON.toJSONString(dockCompanyUserClockDTO), projUid);
//                } catch (Exception e) {
//                    e.printStackTrace();
//                }
//            }
//
//        });

        return;
    }

    private void wenHuaZhongXinClockHandaler(DatapushDTO datapushDTO) {
        JSONObject data = datapushDTO.getData();
        String cardOrGateId = data.getString("personId");
        //设备编号查询闸机
        Gate gate = null;
        String deviceId = datapushDTO.getDevice_id();
        if (StringUtils.isNotBlank(cardOrGateId)) {
            List<UserProjectDTO> userProjectDTOS;
            //先判断是否是自定义的id
            if (cardOrGateId.startsWith(Gate.getIdPre())){
                String userId = cardOrGateId.replaceAll(Gate.getIdPre(), "");
                userProjectDTOS = userProjectMapper.findByGateLinkId(Integer.valueOf(userId));
            }else {
                userProjectDTOS = userProjectMapper.findByCardOrGateIdToDock(cardOrGateId);
            }

            if (userProjectDTOS.size() > 0){
                UserProjectDTO userProjectDTO;
                QueryWrapper<Gate> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("code_",deviceId);
                //多人在岗时通过闸机查人员，一人在岗人员tenantId设备编号查询闸机
                if (userProjectDTOS.size() ==1){
                    userProjectDTO = userProjectDTOS.get(0);
                    queryWrapper.eq("tenant_id_",userProjectDTO.getTenantId());
                    //根据闸机tenantId区分人员
                    List<Gate> gates = gateMapper.selectList(queryWrapper);
                    if (null != gates && gates.size() > 0){
                        gate = gates.get(0);
                    }
                }else {
                    //根据闸机tenantId区分人员
                    List<Gate> gates = gateMapper.selectList(queryWrapper);
                    Set<String> tIds = gates.stream().map(g -> g.getTenantId())
                            .collect(Collectors.toSet());
                    List<UserProjectDTO> projectDTOS = userProjectDTOS.stream()
                            .filter(u -> tIds.contains(u.getTenantId()))
                            .collect(Collectors.toList());
                    if (projectDTOS.size() > 0){
                        userProjectDTO = projectDTOS.get(0);
                    }else {
                        //万一取不到就随机取一个
                        userProjectDTO = userProjectDTOS.get(0);
                    }
                    List<Gate> gateList = gates.stream()
                            .filter(g -> userProjectDTO.getTenantId().equals(g.getTenantId()))
                            .collect(Collectors.toList());
                    if (gateList.size() > 0){
                        gate = gateList.get(0);
                    }
                }
                //根据userproject生成考勤上报信息dockCompanyUserClockDTO
                DockCompanyUserClockDTO dockCompanyUserClockDTO = dockUserProjectToUserClock(userProjectDTO, deviceId, gate, data);
                //考勤接口
                String userClockAddUrlPath = urlPrefix + "/api_v1/modules/issueinfo/addPlatAttendanceInfo";
                //发送post请求
                try {
                    HttpClientUtil.doPostApply(userClockAddUrlPath, JSON.toJSONString(dockCompanyUserClockDTO), projUid);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private DockCompanyUserClockDTO dockUserProjectToUserClock(UserProjectDTO userProjectDTO, String deviceCode, Gate gate, JSONObject data) {
        DockCompanyUserClockDTO dockCompanyUserClockDTO = new DockCompanyUserClockDTO();
        dockCompanyUserClockDTO.setDeviceId(deviceCode);
        //获取参建单位第三方id
        LaborCompanyProject laborCompanyProject = laborCompanyProjectService.getById(userProjectDTO.getCompanyProjectId());
        dockCompanyUserClockDTO.setCompany(laborCompanyProject.getSysDockId());
        List<DockUserClockDTO> dockUserClockDTOList = new ArrayList<>();
        DockUserClockDTO dockUserClockDTO = new DockUserClockDTO();
        //获取班组第三方id
        Group group = groupService.getById(userProjectDTO.getGroupId());
        dockUserClockDTO.setTeamName(group.getName());
        dockUserClockDTO.setTeamUid(group.getSysDockId());
        //获取人员第三方id
        dockUserClockDTO.setWorkerUid(userProjectDTO.getSysDockId());
        dockUserClockDTO.setWorkerName(userProjectDTO.getUserName());
        dockUserClockDTO.setDirection(gate.getDirection() == 1 ? "01" : "02");
        dockUserClockDTO.setDeviceName(StringUtils.isBlank(gate.getName()) ? "考勤机" : gate.getName());
        dockUserClockDTO.setIdcardType(1);
        dockUserClockDTO.setIdcardNumber(userProjectDTO.getCard());
        dockUserClockDTO.setDate(data.getString("capTime"));
        if (StringUtils.isBlank(data.getString("closeupPic"))) {
            dockUserClockDTO.setSnapshot(defaultBase64Pic);
        } else {
            String base64str = ImageUtil.getImgFileToBase64(data.getString("closeupPic"));
            dockUserClockDTO.setSnapshot(base64str);
        }
        dockUserClockDTOList.add(dockUserClockDTO);
        dockCompanyUserClockDTO.setDataList(dockUserClockDTOList);
        return dockCompanyUserClockDTO;
    }

    private DockUserClockDTO dockUserGateToUserClock(UserClock userClock, Map<String, DockUserDTO> dockUserExDTOMap, Map<String, DockGroupExDTO> dockGroupMap) {
        DockUserClockDTO  dockUserClockDTO = new DockUserClockDTO();
        dockUserClockDTO.setIdcardType(dockUserExDTOMap.get(userClock.getUserId()).getIdcardType());
        dockUserClockDTO.setIdcardNumber(dockUserExDTOMap.get(userClock.getUserId()).getIdcardNum());
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        dockUserClockDTO.setDate(sdf.format(userClock.getClockTime()));
        dockUserClockDTO.setDirection(userClock.getDirection() == 1 ? "01" : "02");
        dockUserClockDTO.setDeviceName("人脸机");
        dockUserClockDTO.setWorkerName(userClock.getUserName());
        //url->base64
        if (StringUtils.isBlank(userClock.getPhoto())) {
            dockUserClockDTO.setSnapshot(defaultBase64Pic);
        } else {
            String base64Str = ImageUtil.getImgFileToBase64(userClock.getPhoto());
            dockUserClockDTO.setSnapshot(base64Str);
        }
        dockUserClockDTO.setTeamName(dockUserExDTOMap.get(userClock.getUserId()).getWorkerUid());
        dockUserClockDTO.setTeamName(dockGroupMap.get(userClock.getGroupId()).getTeamName());
        dockUserClockDTO.setTeamUid(dockGroupMap.get(userClock.getGroupId()).getTeamUid());
        dockUserClockDTO.setWorkerUid(dockUserExDTOMap.get(userClock.getUserId()).getWorkerUid());
        return dockUserClockDTO;
    }

    private DockUserDTO dockUserProjectDTOToUser(UserProjectDTO userProjectDTO) {
        DockUserDTO dockUserDTO = new DockUserDTO();
        dockUserDTO.setGender(userProjectDTO.getGender() - 1);
        dockUserDTO.setName(userProjectDTO.getUserName());
        dockUserDTO.setCulture("99");
        dockUserDTO.setAddress(StringUtils.isBlank(userProjectDTO.getAddress()) ? "blank" : userProjectDTO.getAddress());
        dockUserDTO.setCellphone(StringUtils.isBlank(userProjectDTO.getTelephone()) ? "blank" : userProjectDTO.getTelephone());
        dockUserDTO.setPolitics("13");
        dockUserDTO.setNation(StringUtils.isBlank(userProjectDTO.getNation()) ? "汉" : userProjectDTO.getNation());
        dockUserDTO.setIdcardNum(StringUtils.isBlank(userProjectDTO.getCard()) ? UUID.randomUUID().toString() : userProjectDTO.getCard());
        dockUserDTO.setIdcardType(1);
        if ("2".equals(userProjectDTO.getType())) {
            dockUserDTO.setWorkType(20);
            dockUserDTO.setWorkTypeCode(workTypeCodeConverse(userProjectDTO.getWorkType()));
        }
        else{
            dockUserDTO.setWorkType(10);
            dockUserDTO.setWorkTypeCode("900");
            dockUserDTO.setManageType(manageTypeConverse(userProjectDTO.getWorkType()));
        }
        dockUserDTO.setCardPublish(StringUtils.isBlank(userProjectDTO.getAuthority()) ? "blank" : userProjectDTO.getAuthority());
        if (userProjectDTO.getIsGroupLeader() == null) dockUserDTO.setIsTeamleader("否");
        else dockUserDTO.setIsTeamleader(userProjectDTO.getIsGroupLeader() == 0 ? "否" : "是");
        if (StringUtils.isBlank(userProjectDTO.getCardA())) dockUserDTO.setSelfImage(defaultBase64Pic);
        else dockUserDTO.setSelfImage(ImageUtil.getImgFileToBase64(userProjectDTO.getCardA()));
        return dockUserDTO;
    }

    /**
     * 计算切分次数
     */
    private Integer countStep(Integer size) {
        return (size + MAX_NUMBER - 1) / MAX_NUMBER;
    }

    /**
     * 管理人员类型数据转换
     * @param manageType
     * @return
     */
    private String manageTypeConverse(String manageType) {
        String[] strings = manageType.split("/");
        String mt = strings[strings.length - 1];
        if ("总监理工程师".equals(mt)) {return "1001";}
        if ("副总监理工程师".equals(mt)) {return "1002";}
        if ("安全监理工程师".equals(mt)) {return "1003";}
        if ("专业监理工程师".equals(mt)) {return "1004";}
        if ("监理工程师".equals(mt)) {return "1005";}
        if ("监理员".equals(mt)) {return "1006";}
        if ("监理安全员".equals(mt)) {return "1007";}
        if ("项目总工程师".equals(mt)) {return "1008";}
        if ("项目经理".equals(mt)) {return "1009";}
        if ("工程经理".equals(mt)) {return "1010";}
        if ("项目技术负责人".equals(mt)) {return "1011";}
        if ("项目工程师".equals(mt)) {return "1012";}
        if ("项目管理员".equals(mt)) {return "1013";}
        if ("项目副经理".equals(mt)) {return "1014";}
        if ("项目总监".equals(mt)) {return "1015";}
        if ("施工员".equals(mt)) {return "1016";}
        if ("质量员".equals(mt)) {return "1017";}
        if ("安全员".equals(mt)) {return "1018";}
        if ("标准员".equals(mt)) {return "1019";}
        if ("材料员".equals(mt)) {return "1020";}
        if ("机械员".equals(mt)) {return "1021";}
        if ("劳务员".equals(mt)) {return "1022";}
        if ("资料员".equals(mt)) {return "1023";}
        if ("总监理工程师代表".equals(mt)) {return "1024";}
        if ("测量员".equals(mt)) {return "1025";}
        if ("试验员".equals(mt)) {return "1026";}
        if ("造价员".equals(mt)) {return "1027";}
        if ("质量负责人".equals(mt)) {return "1028";}
        if ("安全负责人".equals(mt)) {return "1029";}
        if ("技术负责人".equals(mt)) {return "1030";}
        if ("生产经理".equals(mt)) {return "1031";}
        if ("物资材料工程师".equals(mt)) {return "1032";}
        return "1099";
    }

    /**
     * 工人工种数据转换
     * @param workType
     * @return
     */
    private String workTypeCodeConverse(String workType) {
        String[] strings = workType.split("/");
        String wt = strings[strings.length - 1];
        if ("砌筑工".equals(wt)) {return "010";}
        if ("钢筋工".equals(wt)) {return "020";}
        if ("架子工".equals(wt)) {return "030";}
        if ("混凝土工".equals(wt)) {return "040";}
        if ("模板工".equals(wt)) {return "050";}
        if ("机械设备安装工".equals(wt)) {return "060";}
        if ("通风工".equals(wt)) {return "070";}
        if ("安装起重工".equals(wt)) {return "080";}
        if ("安装钳工".equals(wt)) {return "090";}
        if ("电气设备安装调试工".equals(wt)) {return "100";}
        if ("管道工".equals(wt)) {return "110";}
        if ("变电安装工".equals(wt)) {return "120";}
        if ("建筑电工".equals(wt)) {return "130";}
        if ("司泵工".equals(wt)) {return "150";}
        if ("挖掘铲运和桩工机械司机".equals(wt)) {return "150";}
        if ("桩机操作工".equals(wt)) {return "160";}
        if ("起重信号工".equals(wt)) {return "170";}
        if ("建筑起重机械安装拆卸工".equals(wt)) {return "180";}
        if ("装饰装修工".equals(wt)) {return "190";}
        if ("室内成套设施安装工".equals(wt)) {return "200";}
        if ("建筑门窗幕墙安装工".equals(wt)) {return "210";}
        if ("幕墙制作工".equals(wt)) {return "220";}
        if ("防水工".equals(wt)) {return "230";}
        if ("木工".equals(wt)) {return "240";}
        if ("石工".equals(wt)) {return "250";}
        if ("电焊工".equals(wt)) {return "270";}
        if ("爆破工".equals(wt)) {return "280";}
        if ("除尘工".equals(wt)) {return "290";}
        if ("测量放线工".equals(wt)) {return "300";}
        if ("线路架设工".equals(wt)) {return "310";}
        if ("古建筑传统石工".equals(wt)) {return "320";}
        if ("古建筑传统瓦工".equals(wt)) {return "330";}
        if ("古建筑传统彩画工".equals(wt)) {return "340";}
        if ("古建筑传统木工".equals(wt)) {return "350";}
        if ("古建筑传统油工".equals(wt)) {return "360";}
        if ("金属工".equals(wt)) {return "380";}
        if ("杂工".equals(wt)) {return "390";}
        if ("管理人员".equals(wt)) {return "900";}
        return "1000";
    }


    /**
     * 单位类型数据转换
     * @param unitType
     * @return
     */
    private String unitTypeConverse(String unitType) {
        if ("1".equals(unitType)) {return "001";}
        if ("2".equals(unitType)) {return "006";}
        if ("3".equals(unitType)) {return "002";}
        if ("4".equals(unitType)) {return "003";}
        if ("5".equals(unitType)) {return "004";}
        if ("6".equals(unitType)) {return "005";}
        if ("7".equals(unitType)) {return "007";}
        if ("8".equals(unitType)) {return "010";}
        if ("9".equals(unitType)) {return "011";}
        if ("10".equals(unitType)) {return "012";}
        if ("11".equals(unitType)) {return "012";}
        if ("12".equals(unitType)) {return "008";}
        if ("13".equals(unitType)) {return "012";}
        return "012";
    }

    //默认的base64照片
    private static final String defaultBase64Pic = "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";


}
